﻿using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using iWare.Wms.Core;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Serilog;
using Yitter.IdGenerator;

namespace iWare.Wms.Application.PDA
{
    /// <summary>
    /// 出库服务
    /// </summary>
    [Route("api/IssueHousing")]
    [ApiDescriptionSettings("PDA", Name = "IssueHousing", Order = 1)]

    public class IssueHousingService : IDynamicApiController, ITransient
    {
        private readonly IRepository<WareArea, MasterDbContextLocator> _wareAreaRep; //库区仓储
        private readonly IRepository<WareOrder, MasterDbContextLocator> _wareOrderRep; //单据仓储
        private readonly IRepository<WareOrderDetails, MasterDbContextLocator> _wareOrderDetailsRep; //单据明细仓储
        private readonly IRepository<WareContainer, MasterDbContextLocator> _wareContainerRep; //容器仓储
        private readonly IRepository<WareLocation, MasterDbContextLocator> _wareLocationRep; //库位仓储
        private readonly IRepository<WareTask, MasterDbContextLocator> _wareTaskRep; //任务仓储
        private readonly IRepository<WareStock, MasterDbContextLocator> _wareStockRep; //库存仓储
        private readonly IRepository<WareSortOrder, MasterDbContextLocator> _wareSortOrderRep; //分拣仓储
        private readonly IRepository<WareContainerVsMaterial, MasterDbContextLocator> _wareContainerVsMaterialRep; //容器与物料关系仓储
        private readonly IRepository<WareLocationVsContainer, MasterDbContextLocator> _wareLocationVsContainerRep; //库位与容器关系仓储 
        private readonly IRepository<WareAgvTask, MasterDbContextLocator> _wareAgvTaskRep; //AGV任务仓储
        private readonly IRepository<WareDictData, MasterDbContextLocator> _wareDictDataRep; //仓库字典值仓储
        private readonly AgvService _agvService; //AGV服务
        private readonly SysConfigService _sysConfigService; //AGV环境服务

        #region 默认
        /// <summary>
        /// 默认
        /// </summary>
        /// <param name="wareAreaRep"></param>
        /// <param name="wareOrderRep"></param>
        /// <param name="wareOrderDetailsRep"></param>
        /// <param name="wareContainerRep"></param>
        /// <param name="wareLocationRep"></param>
        /// <param name="wareTaskRep"></param>
        /// <param name="wareStockRep"></param>
        /// <param name="wareSortOrderRep"></param>
        /// <param name="wareContainerVsMaterialRep"></param>
        /// <param name="wareLocationVsContainerRep"></param>
        /// <param name="wareAgvTaskRep"></param>
        /// <param name="wareDictDataRep"></param>
        /// <param name="agvService"></param>
        /// <param name="sysConfigService"></param>
        public IssueHousingService(
             IRepository<WareArea, MasterDbContextLocator> wareAreaRep,
             IRepository<WareOrder, MasterDbContextLocator> wareOrderRep,
             IRepository<WareOrderDetails, MasterDbContextLocator> wareOrderDetailsRep,
             IRepository<WareContainer, MasterDbContextLocator> wareContainerRep,
             IRepository<WareLocation, MasterDbContextLocator> wareLocationRep,
             IRepository<WareTask, MasterDbContextLocator> wareTaskRep,
             IRepository<WareStock, MasterDbContextLocator> wareStockRep,
             IRepository<WareSortOrder, MasterDbContextLocator> wareSortOrderRep,
             IRepository<WareContainerVsMaterial, MasterDbContextLocator> wareContainerVsMaterialRep,
             IRepository<WareLocationVsContainer, MasterDbContextLocator> wareLocationVsContainerRep,
             IRepository<WareAgvTask, MasterDbContextLocator> wareAgvTaskRep,
             IRepository<WareDictData, MasterDbContextLocator> wareDictDataRep,
             AgvService agvService, //AGV服务
             SysConfigService sysConfigService  
        )
        {
            _sysConfigService = sysConfigService;
            _wareAreaRep = wareAreaRep;
            _wareOrderRep = wareOrderRep;
            _wareOrderDetailsRep = wareOrderDetailsRep;
            _wareContainerRep = wareContainerRep;
            _wareLocationRep = wareLocationRep;
            _wareTaskRep = wareTaskRep;
            _wareStockRep = wareStockRep;
            _wareSortOrderRep = wareSortOrderRep;
            _wareContainerVsMaterialRep = wareContainerVsMaterialRep;
            _wareLocationVsContainerRep = wareLocationVsContainerRep;
            _wareDictDataRep = wareDictDataRep;
            _wareAgvTaskRep = wareAgvTaskRep;
            _agvService = agvService;
        }
        #endregion

        /// <summary>
        /// 自动库单据/托盘出库  目前单据下发不支持重复操作
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("WarehouseOut")]
        [UnitOfWork]
        public async Task WarehouseOut([FromBody] OutboundInput input)
        {
            // 查询单据明细信息
            if (string.IsNullOrEmpty(input.orderNo) && string.IsNullOrEmpty(input.ContainerCode))
                throw Oops.Oh("请扫描单据或者容器编码！");
            var huanjing =await  _sysConfigService.GetDemoEnvFlag();
            //获取AGV出库放货分拣库位
            var wareAgvLocationList = await _wareLocationRep.Where(z => z.LocationStatus == LocationStatusEnum.kongxian && z.AreaID == 410594643796037 && z.IsLock == YesOrNot.N).ToListAsync();
            
            if (input.taskModel == TaskModel.ZIDONG)
            {
                if (wareAgvLocationList.Count == 0) throw Oops.Oh(errorMessage: "无分拣库位，请稍后下发！");
            }
            
            if (!string.IsNullOrEmpty(input.ContainerCode))
            {
                //获取一条空闲的agv站点信息
                var agvLocationModel = wareAgvLocationList.FirstOrDefault();

                //检查库位与容器关系
                var wareLocationVsContainer = await _wareLocationVsContainerRep.DetachedEntities.FirstOrDefaultAsync(
                    n => n.ContainerCode == input.ContainerCode && n.LocationVsContainerStatus == CommonStatus.ENABLE);
                if (wareLocationVsContainer == null) throw Oops.Oh("托盘库位关系不存在！");
                //检查托盘
                var wareContainer = await _wareContainerRep.DetachedEntities.FirstOrDefaultAsync(n => n.Code == input.ContainerCode && n.ContainerStatus == ContainerStatusEnum.kuwei);
                if (wareContainer == null) throw Oops.Oh("托盘不存在！");
                //检查库位
                var locationModel = await _wareLocationRep.DetachedEntities.FirstOrDefaultAsync(p => p.Code == wareLocationVsContainer.LocationCode && p.LocationStatus == LocationStatusEnum.cunhuo);
                if (locationModel == null) throw Oops.Oh("库位不存在！");

                //物料和容器的关系
                var cvmModelList = await _wareContainerVsMaterialRep.DetachedEntities.Where(z =>
                  z.ContainerCode == input.ContainerCode && z.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();

                if (wareContainer.AreaID == 374444843716677) 
                {
                    agvLocationModel = wareAgvLocationList.Where(z => z.RowNo == 1 && z.LocationStatus == LocationStatusEnum.kongxian).FirstOrDefault();
                }
                else
                {
                    agvLocationModel = wareAgvLocationList.Where(z => z.RowNo == 2 && z.LocationStatus == LocationStatusEnum.kongxian).FirstOrDefault();
                }
                if (agvLocationModel == null) throw Oops.Oh(errorMessage: "无分拣库位，请稍后下发！");

                //1.新增任务
                var OrderNo = "N/A";
                if (cvmModelList.Count > 0) OrderNo = cvmModelList.FirstOrDefault().OrderNo;
                var taskNo = YitIdHelper.NextId().ToString();
                var taskModel = new WareTask()
                {
                    OrderNo = OrderNo,
                    TaskModel = input.taskModel == TaskModel.SHOUDONG ? TaskModel.SHOUDONG : TaskModel.ZIDONG,
                    TaskType = TaskType.Out,
                    TaskNo = taskNo,
                    TaskName = "N/A",
                    TaskStatus = TaskStatusEnum.NotProgress,
                    Priority = 1,
                    ContainerCode = input.ContainerCode,
                    IsRead = false,
                    FromLocationCode = wareLocationVsContainer.LocationCode,
                    ToLocationCode = "N/A"
                };
                //新增任务
                await _wareTaskRep.InsertNowAsync(taskModel);

                //需要区分是立体库还是平库
                if (wareContainer.AreaID == 374444843716677) //立体库
                {
                    taskModel.IsRead = true;

                    //更新库位状态
                    locationModel.LocationStatus = LocationStatusEnum.daichu;
                    await _wareLocationRep.UpdateAsync(locationModel);
                    if (taskModel.TaskModel == TaskModel.ZIDONG)
                    {
                        //更新agv分拣库位状态
                        agvLocationModel.LocationStatus = LocationStatusEnum.dairu;
                        await _wareLocationRep.UpdateAsync(agvLocationModel);

                        //更新任务目的地位置
                        taskModel.ToLocationCode = agvLocationModel.Code;
                    }
                }
                else
                {
                    if (taskModel.TaskModel == TaskModel.SHOUDONG)
                    {
                        var contionCode = wareContainer.Code;
                        var contionId = wareContainer.Id;

                        //2.新增出库记录
                        foreach (var item in cvmModelList)
                        {
                            item.ContainerVsMaterialStatus = CommonStatus.DELETED;
                            await _wareContainerVsMaterialRep.UpdateAsync(item);
                        }
                        foreach (var item in cvmModelList)
                        {
                            //新增一条组盘信息
                            var model = item.Adapt<WareContainerVsMaterial>();
                            model.Id = YitIdHelper.NextId();
                            model.OrderNo = YitIdHelper.NextId().ToString();
                            model.ContainerCode = wareContainer.Code;
                            model.ContainerId = wareContainer.Id;
                            model.ContainerVsMaterialStatus = CommonStatus.ENABLE;
                            await _wareContainerVsMaterialRep.InsertAsync(model);
                        }

                        //更新库存信息
                        var stockModel = await _wareStockRep.Where(z => z.ContainerCode == input.ContainerCode).ToListAsync();
                        if (stockModel != null)
                        {
                            foreach (var item in stockModel)
                            {
                                item.LocationCode = "N/A";
                                await _wareStockRep.UpdateAsync(item);
                            }
                        }
                        //修改托盘状态
                        wareContainer.ContainerStatus = ContainerStatusEnum.zupan;
                        await _wareContainerRep.UpdateAsync(wareContainer);
                        //修改库位状态
                        locationModel.LocationStatus = LocationStatusEnum.kongxian;
                        await _wareLocationRep.UpdateAsync(locationModel);
                        //修改库位容器状态
                        wareLocationVsContainer.LocationVsContainerStatus = CommonStatus.DELETED;
                        await _wareLocationVsContainerRep.UpdateAsync(wareLocationVsContainer);
                        //更改任务状态
                        taskModel.TaskStatus = TaskStatusEnum.Complete;
                    }
                    else
                    {
                        

                        //根据库位获取对应的放货层
                        var layNumber = 0;
                        if (locationModel.RowNo == 6)
                        {
                            if (locationModel.LayerNo == 5) layNumber = locationModel.LayerNo + 6;
                            else layNumber = locationModel.LayerNo + 5;

                        }
                        else
                        {
                            if (locationModel.LayerNo == 1) layNumber = locationModel.LayerNo - 1;
                            else layNumber = locationModel.LayerNo;
                        }
                        // 调用AGV服务创建指定名称的订单
                        var createTransportOrders = new CreateTransportOrdersInput();
                        createTransportOrders.TaskNo = taskNo;
                        createTransportOrders.intendedVehicle = "Vehicle-0002"; //立体库执行车辆
                        var destList = new List<DestinationsInput>();
                        var dest1 = new DestinationsInput()
                        {
                            locationName = locationModel.OriginalLocationCode, //平库对应原库位编号
                            operation = "Load cargo:"+ layNumber.ToString("00") //输送线层对应平库的列，Load是取货
                        };
                        var dest2 = new DestinationsInput()
                        {
                            locationName = agvLocationModel.Code, //地面站点/放料口
                            operation = "Unload cargo:12"  //地面层数是0，Unload是放货
                        };
                        destList.Add(dest1);
                        destList.Add(dest2);

                        createTransportOrders.destinations = destList;
                        var createTransportOrdersOutput = await _agvService.CreateTransportOrders(createTransportOrders);

                        if (createTransportOrdersOutput.result == "success")
                        {
                            // 创建AGV任务
                            var wareAgvTask = new WareAgvTask()
                            {
                                TaskType = "出库",
                                StartPlace = locationModel.Code,
                                EndPlace = agvLocationModel.Code, //地面站点/放料口
                                TransportOrder = taskNo,
                                AgvState = "PRISTINE",
                                ContainerCode = input.ContainerCode,
                                CreatedUserName = CurrentUserInfo.Name
                            };
                            await _wareAgvTaskRep.InsertAsync(wareAgvTask);
                        }

                        //更新任务目的地位置
                        taskModel.ToLocationCode = agvLocationModel.Code;

                        //更新库位状态
                        locationModel.LocationStatus = LocationStatusEnum.daichu;
                        await _wareLocationRep.UpdateAsync(locationModel);
                        //更新agv分拣库位状态
                        agvLocationModel.LocationStatus = LocationStatusEnum.dairu;
                        await _wareLocationRep.UpdateAsync(agvLocationModel);
                    }
                }
                
                //修改任务信息
                await _wareTaskRep.UpdateAsync(taskModel);
            }
            else
            {
                var orderCategory = (await _wareDictDataRep.FirstOrDefaultAsync(z => z.Value == input.typeWay)).Code;
                var orderModel = await _wareOrderRep.FirstOrDefaultAsync(n => n.OrderNo == input.orderNo && n.OrderCategory == orderCategory);
                if (orderModel == null) throw Oops.Oh("单据信息不存在！");
                var orderDetailsList = await _wareOrderDetailsRep.Where(z => z.OrderId == orderModel.Id && z.OrderQuantity != z.ActualQuantity).ToListAsync();
                if (orderDetailsList.Count == 0) throw Oops.Oh("单据明细不存在！");
                //查询单据中的物料库存并赋值对应的字段属性(库位，容器，下发数量)
                var stockList = await _wareStockRep.Where(p => orderDetailsList.Select(n => n.Code).ToList().Contains(p.Code) && p.LocationCode != "N/A" && !string.IsNullOrEmpty(p.LocationCode) 
            && (p.ContainerCode.StartsWith("TJ") || p.ContainerCode.StartsWith("P-TM") || p.ContainerCode.StartsWith("WG"))).ToListAsync();
                if (stockList.Count < 1) throw Oops.Oh("单据明细无库存信息！");
                //构建新的出库的单据

                foreach (var item in orderDetailsList)
                {
                    //库存先进先出的原则和数量满足的原则
                    var ckstcokList = stockList.Where(p => p.Code == item.Code).OrderBy(n => n.CreatedTime).OrderByDescending(n => n.CurrentQuantity).ToList();

                    foreach (var stockModel in ckstcokList)
                    {
                        if (stockModel.ContainerCode.StartsWith("WG")) break;
                        item.LocationCode = stockModel.LocationCode;
                        item.ContainerCode = stockModel.ContainerCode;
                        break;
                    }
                }
                //更新单据明细和主表
                await _wareOrderDetailsRep.UpdateAsync(orderDetailsList);
                orderModel.OrderStatus = IssueStausEnum.ZHIXINGZHONG;

                //以托盘为单位进行出库操作
                var containerCodeList = orderDetailsList.Select(z => z.ContainerCode).Distinct();
                //获取分拣库区
                var wareAgvLocation = await _wareLocationRep.FirstOrDefaultAsync(z => z.LocationStatus == LocationStatusEnum.kongxian && z.AreaID == 410594643796037);

                foreach (var containerCode in containerCodeList.Take(wareAgvLocationList.Count))
                {
                    if (containerCode == null) continue;
                    if (containerCode.StartsWith("WG")) continue;
                    if (containerCode.StartsWith("TJ") && wareAgvLocationList.Where(z => z.RowNo == 1 && z.LocationStatus == LocationStatusEnum.kongxian).Count() < 1) continue;
                    if (containerCode.StartsWith("P-TM") && wareAgvLocationList.Where(z => z.RowNo == 2 && z.LocationStatus == LocationStatusEnum.kongxian).Count() < 1) continue;

                    //获取托盘上的单据明细
                    var containerOrderDetailsList = orderDetailsList.Where(z => z.ContainerCode == containerCode).ToList();
                    //检查库位与容器关系
                    var wareLocationVsContainer = await _wareLocationVsContainerRep.FirstOrDefaultAsync(
                        n => n.ContainerCode == containerCode && n.LocationVsContainerStatus == CommonStatus.ENABLE);
                    if (wareLocationVsContainer == null) throw Oops.Oh("托盘库位关系不存在！");

                    //检查托盘
                    var wareContainer = await _wareContainerRep.FirstOrDefaultAsync(n => n.Code == containerCode && n.ContainerStatus == ContainerStatusEnum.kuwei);
                    if (wareContainer == null) throw Oops.Oh("托盘不存在！");
                    //检查库位
                    var locationModel = await _wareLocationRep.FirstOrDefaultAsync(p => p.Code == wareLocationVsContainer.LocationCode && p.LocationStatus == LocationStatusEnum.cunhuo);
                    if (locationModel == null) throw Oops.Oh("库位不存在！");

                    //物料和容器的关系
                    var cvmModelList = await _wareContainerVsMaterialRep.Where(z =>
                      z.ContainerCode == containerCode && z.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();

                    //1.新增任务
                    var OrderNo = "N/A";
                    if (cvmModelList.Count > 0) OrderNo = cvmModelList.FirstOrDefault().OrderNo;
                    var taskNo = YitIdHelper.NextId().ToString();
                    var taskModel = new WareTask()
                    {
                        OrderNo = OrderNo,
                        TaskModel = input.taskModel == TaskModel.SHOUDONG ? TaskModel.SHOUDONG : TaskModel.ZIDONG,
                        TaskType = TaskType.Out,
                        TaskNo = taskNo,
                        TaskName = orderModel.OrderType == IssueTypeEnum.DIAOBO ? TaskNameConst.DiaoBoDan_ManualOut : TaskNameConst.ShouDongDan_ManualOut,
                        TaskStatus = TaskStatusEnum.NotProgress,
                        Priority = 1,
                        ContainerCode = containerCode,
                        IsRead = false,
                        FromLocationCode = locationModel.Code,
                        ToLocationCode = "N/A",
                    };
                    //新增任务
                    await _wareTaskRep.InsertNowAsync(taskModel);
                    //循环创建分拣记录表
                    foreach (var item in containerOrderDetailsList)
                    {
                        var ckstockModel = stockList.FirstOrDefault(p => p.Code == item.Code && p.LocationCode == item.LocationCode);
                        var number = item.OrderQuantity - item.ActualQuantity;
                        if (number == 0) continue;
                        if (ckstockModel.CurrentQuantity >= number)
                        {
                            item.ActualQuantity += number;
                            ckstockModel.CurrentQuantity -= number;
                        }
                        else
                        {
                            item.ActualQuantity += ckstockModel.CurrentQuantity;
                            number = ckstockModel.CurrentQuantity;
                            ckstockModel.CurrentQuantity = 0;
                        }
                        //更新库存
                        await _wareStockRep.UpdateAsync(ckstockModel);
                        await _wareOrderDetailsRep.UpdateAsync(item);

                        // 新增分拣
                        var wareSortOrder = new WareSortOrder()
                        {
                            OrderNo = orderModel.OrderNo,
                            OrderDetailID = item.Id,
                            ContainerCode = item.ContainerCode,
                            ContainerOrderNo = OrderNo,
                            ProjectCode = item.ProjectCode,
                            Code = item.Code,
                            Name = item.Name,
                            LocationCode = locationModel.Code,
                            SpecificationModel = item.SpecificationModel,
                            Unit = item.Unit ?? "",
                            InspectionMethod = item.InspectionMethod,
                            SortQuantity = number,
                            ActualQuantity = new decimal(0.00)
                        };
                        await _wareSortOrderRep.InsertAsync(wareSortOrder);
                    }
                    //需要区分是立体库还是平库
                    if (containerCode.StartsWith("TJ"))
                    {
                        taskModel.IsRead = true;
                        //更新库位状态
                        locationModel.LocationStatus = LocationStatusEnum.daichu;
                        await _wareLocationRep.UpdateAsync(locationModel);
                        if (taskModel.TaskModel == TaskModel.ZIDONG)
                        {
                            //更新任务目的地位置
                            taskModel.ToLocationCode = wareAgvLocationList.Where(z => z.RowNo == 1 && z.LocationStatus == LocationStatusEnum.kongxian).FirstOrDefault().Code;

                            //更新agv分拣库位状态
                            wareAgvLocationList.Where(z => z.RowNo == 1 && z.LocationStatus == LocationStatusEnum.kongxian).FirstOrDefault().LocationStatus = LocationStatusEnum.dairu;
                        }
                    }
                    else
                    {
                        if (taskModel.TaskModel == TaskModel.SHOUDONG)
                        {
                            //2.新增出库记录
                            foreach (var item in cvmModelList)
                            {
                                item.ContainerVsMaterialStatus = CommonStatus.DELETED;
                                await _wareContainerVsMaterialRep.UpdateAsync(item);
                            }
                            foreach (var item in cvmModelList)
                            {
                                //新增一条组盘信息
                                var model = item.Adapt<WareContainerVsMaterial>();
                                model.Id = YitIdHelper.NextId();
                                model.OrderNo = YitIdHelper.NextId().ToString();
                                model.ContainerCode = wareContainer.Code;
                                model.ContainerId = wareContainer.Id;
                                model.ContainerVsMaterialStatus = CommonStatus.ENABLE;
                                await _wareContainerVsMaterialRep.InsertAsync(model);
                            }

                            //更新库存信息
                            var stockModel = stockList.Where(z => z.ContainerCode == containerCode).ToList();
                            if (stockModel != null)
                            {
                                foreach (var item in stockModel)
                                {
                                    item.LocationCode = "N/A";
                                    await _wareStockRep.UpdateAsync(item);
                                }
                            }
                            //修改托盘状态
                            wareContainer.ContainerStatus = ContainerStatusEnum.fenjian;
                            await _wareContainerRep.UpdateAsync(wareContainer);
                            //修改库位状态
                            locationModel.LocationStatus = LocationStatusEnum.kongxian;
                            await _wareLocationRep.UpdateAsync(locationModel);
                            //修改库位容器状态
                            wareLocationVsContainer.LocationVsContainerStatus = CommonStatus.DELETED;
                            await _wareLocationVsContainerRep.UpdateAsync(wareLocationVsContainer);
                        }
                        else
                        {
                            //根据库位获取对应的放货层
                            var layNumber = 0;
                            if (locationModel.RowNo == 6)
                            {
                                if (locationModel.LayerNo == 5) layNumber = locationModel.LayerNo + 6;
                                else layNumber = locationModel.LayerNo + 5;
                            }
                            else
                            {
                                if (locationModel.LayerNo == 1) layNumber = locationModel.LayerNo - 1;
                                else layNumber = locationModel.LayerNo;
                            }
                            // 调用AGV服务创建指定名称的订单
                            var createTransportOrders = new CreateTransportOrdersInput();
                            createTransportOrders.TaskNo = taskNo;
                            createTransportOrders.intendedVehicle = "Vehicle-0002"; //立体库执行车辆
                            var destList = new List<DestinationsInput>();
                            var dest1 = new DestinationsInput()
                            {
                                locationName = locationModel.OriginalLocationCode, //平库对应原库位编号
                                operation = "Load cargo:" + layNumber.ToString("00") //输送线层对应平库的列，Load是取货
                            };
                            var dest2 = new DestinationsInput()
                            {
                                locationName = wareAgvLocationList.Where(z => z.RowNo == 2 && z.LocationStatus == LocationStatusEnum.kongxian).FirstOrDefault().Code, //地面站点/放料口
                                operation = "Unload cargo:12"  //地面层数是0，Unload是放货
                            };
                            destList.Add(dest1);
                            destList.Add(dest2);

                            createTransportOrders.destinations = destList;
                            var createTransportOrdersOutput = await _agvService.CreateTransportOrders(createTransportOrders);
                            if (createTransportOrdersOutput.result == "success")
                            {
                                // 创建AGV任务
                                var wareAgvTask = new WareAgvTask()
                                {
                                    TaskType = "出库",
                                    StartPlace = locationModel.Code,
                                    EndPlace = wareAgvLocationList.Where(z => z.RowNo == 2 && z.LocationStatus == LocationStatusEnum.kongxian).FirstOrDefault().Code, //地面站点/放料口
                                    TransportOrder = taskNo,
                                    AgvState = "PRISTINE",
                                    ContainerCode = containerCode,
                                    CreatedUserName = CurrentUserInfo.Name
                                };
                                await _wareAgvTaskRep.InsertAsync(wareAgvTask);
                            }

                            //更新库位状态
                            locationModel.LocationStatus = LocationStatusEnum.daichu;
                            await _wareLocationRep.UpdateAsync(locationModel);
                            //更新任务目的地位置
                            taskModel.ToLocationCode = wareAgvLocationList.Where(z => z.RowNo == 2 && z.LocationStatus == LocationStatusEnum.kongxian ).FirstOrDefault().Code;
                            //更新agv分拣库位状态
                            wareAgvLocationList.Where(z => z.RowNo == 2 && z.LocationStatus == LocationStatusEnum.kongxian).FirstOrDefault().LocationStatus = LocationStatusEnum.dairu;
                        }
                    }
                    //更新任务
                    await _wareTaskRep.UpdateAsync(taskModel);
                }
                //更新目标点分拣库位状态
                await _wareLocationRep.UpdateAsync(wareAgvLocationList);

                //重新查询下发总数量
                var orderModel1 = await _wareOrderRep.FirstOrDefaultAsync(n => n.OrderNo == input.orderNo);
                var orderActualSum = _wareOrderDetailsRep.Where(e => e.OrderId == orderModel1.Id).Sum(z => z.ActualQuantity);
                if (orderActualSum == orderModel1.OrderQuantityTotal) orderModel1.OrderStatus = IssueStausEnum.WANCHENG;
                await _wareOrderRep.UpdateAsync(orderModel1);
            }
        }

        /// <summary>
        /// 非自动库单据/库位出库
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("OtherWarehouseOut")]
        [UnitOfWork]
        public async Task OtherWarehouseOut([FromBody] OutboundInput input)
        {
            // 查询单据明细信息
            if (string.IsNullOrEmpty(input.orderNo) && string.IsNullOrEmpty(input.LocationCode))
                throw Oops.Oh("请扫描单据或库位编码！");

            if (!string.IsNullOrEmpty(input.LocationCode))
            {
                //验证库位是否正确

                //检查库位与容器关系
                var wareLocationVsContainer = await _wareLocationVsContainerRep.DetachedEntities.Where(
                    n =>n.LocationCode == input.LocationCode && n.LocationVsContainerStatus == CommonStatus.ENABLE).ProjectToType<WareLocationVsContainer>().FirstOrDefaultAsync();
                if (wareLocationVsContainer == null) throw Oops.Oh("托盘库位关系不存在！");

                //1.1创建出库记录
                var cvmModelList = await _wareContainerVsMaterialRep.Where(z =>
                  z.ContainerCode == wareLocationVsContainer.ContainerCode && z.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();
                foreach (var item in cvmModelList)
                {
                    item.ContainerVsMaterialStatus = CommonStatus.DELETED;
                    await _wareContainerVsMaterialRep.UpdateAsync(item);
                }

                //1.2创建出库任务
                var OrderNo = "N/A";
                if (cvmModelList.Count > 0) OrderNo = cvmModelList.FirstOrDefault().OrderNo;
                var taskModel = new WareTask()
                {
                    OrderNo = OrderNo,
                    TaskModel = TaskModel.SHOUDONG,
                    TaskType = TaskType.Out,
                    TaskNo = YitIdHelper.NextId().ToString(),
                    TaskName = TaskNameConst.ShouDongDan_ManualOut,
                    TaskStatus = TaskStatusEnum.Complete,
                    Priority = 1,
                    ContainerCode = wareLocationVsContainer.ContainerCode,
                    FromLocationCode = wareLocationVsContainer.LocationCode,
                    ToLocationCode = "出库口",
                    UpdatedTime = DateTime.Now,
                    UpdatedUserId = CurrentUserInfo.UserId,
                    UpdatedUserName = CurrentUserInfo.Name,
                };
                await _wareTaskRep.InsertNowAsync(taskModel);

                //1.3扣减库存和组盘数量
                foreach (var item in input.WareContainerVsMaterials)
                {
                    var updatestockModel = await _wareStockRep.FirstOrDefaultAsync(z => z.Code == item.Code && z.ContainerCode == item.ContainerCode);
                    if (updatestockModel == null) continue;

                    if (item.BindQuantity>0)
                    {
                        updatestockModel.StockQuantity = item.BindQuantity;
                        updatestockModel.CurrentQuantity = item.BindQuantity;
                        await _wareStockRep.UpdateAsync(updatestockModel);
                    }
                    else
                    {
                        await _wareStockRep.DeleteAsync(updatestockModel);
                    }
                }

                OrderNo = YitIdHelper.NextId().ToString();
                //2.1新增入库组盘记录
                foreach (var item in input.WareContainerVsMaterials)
                {
                    if (item.BindQuantity <= 0) continue;
                    //新增一条组盘信息
                    var model = item.Adapt<WareContainerVsMaterial>();
                    model.Id = YitIdHelper.NextId();
                    model.OrderNo = OrderNo;
                    model.ContainerCode = wareLocationVsContainer.ContainerCode;
                    model.ContainerId = wareLocationVsContainer.WareContainer.Id;
                    model.ContainerVsMaterialStatus = CommonStatus.ENABLE;
                    await _wareContainerVsMaterialRep.InsertAsync(model);
                }

                //2.2.新增任务
                var taskRkModel = new WareTask()
                {
                    OrderNo = OrderNo,
                    TaskModel = TaskModel.SHOUDONG,
                    TaskType = TaskType.In,
                    TaskNo = YitIdHelper.NextId().ToString(),
                    TaskName = TaskNameConst.ShouDongDan_ManualOut,
                    TaskStatus = TaskStatusEnum.Complete,
                    Priority = 1,
                    ContainerCode = wareLocationVsContainer.ContainerCode,
                    FromLocationCode = "入库口",
                    ToLocationCode = wareLocationVsContainer.LocationCode,
                    UpdatedTime = DateTime.Now,
                    UpdatedUserId = CurrentUserInfo.UserId,
                    UpdatedUserName = CurrentUserInfo.Name,
                };
                await _wareTaskRep.InsertNowAsync(taskRkModel);
            }
            else
            {
                // 查询单据类型对应的ID
                var orderCategory = (await _wareDictDataRep.FirstOrDefaultAsync(z => z.Value == input.typeWay)).Code;
                var orderModel = await _wareOrderRep.DetachedEntities.FirstOrDefaultAsync(n => n.OrderNo == input.orderNo && n.OrderCategory == orderCategory);
                if (orderModel == null) throw Oops.Oh("单据信息不存在！");
                var orderDetailsList = await _wareOrderDetailsRep.DetachedEntities.Where(z => z.OrderId == orderModel.Id && z.OrderQuantity != z.ActualQuantity).ToListAsync();
                if (orderDetailsList == null) throw Oops.Oh("单据明细不存在！");
                //查询单据中的物料库存并赋值对应的字段属性(库位，容器，下发数量)
                var stockList = await _wareStockRep.Where(p => orderDetailsList.Select(n => n.Code).ToList().Contains(p.Code) && p.LocationCode != "N/A" && !string.IsNullOrEmpty(p.LocationCode)
                    && (p.ContainerCode.StartsWith("TJ") || p.ContainerCode.StartsWith("P-TM") || p.ContainerCode.StartsWith("WG"))).ToListAsync();
                if (stockList.Count < 1) throw Oops.Oh("单据明细无库存信息！");
                foreach (var item in orderDetailsList)
                {
                    //库存先进先出的原则和数量满足的原则
                    var ckstcokModelList = stockList.Where(p => p.Code == item.Code).OrderBy(n => n.CreatedTime).OrderByDescending(n => n.CurrentQuantity).ToList();
                    foreach (var stockitem in ckstcokModelList)
                    {
                        if(stockitem.ContainerCode.StartsWith("TJ") || stockitem.ContainerCode.StartsWith("P-TM")) break;
                        item.LocationCode = stockitem.LocationCode;
                        item.ContainerCode = stockitem.ContainerCode;
                        //更新库存
                        await _wareStockRep.UpdateAsync(stockitem);
                        break;
                    }
                }
                //更新单据明细和主表
                await _wareOrderDetailsRep.UpdateAsync(orderDetailsList);
                orderModel.OrderStatus = IssueStausEnum.ZHIXINGZHONG;
                await _wareOrderRep.UpdateAsync(orderModel);
                //以托盘为单位进行出库操作
                var containerCodeList = orderDetailsList.Select(z => z.ContainerCode).Distinct();
                foreach (var containerCode in containerCodeList)
                {
                    if (containerCode == null) continue;
                    if (containerCode.StartsWith("TJ") || containerCode.StartsWith("P-TM")) continue;
                    //根据容器获取单据信息
                    var containerOrderDetailsList = orderDetailsList.Where(z => z.ContainerCode == containerCode).ToList();

                    //检查托盘
                    var wareContainer = await _wareContainerRep.DetachedEntities.FirstOrDefaultAsync(n => n.Code == containerCode && n.ContainerStatus == ContainerStatusEnum.kuwei);
                    if (wareContainer == null) throw Oops.Oh("托盘不存在！");
                    //检查库位与容器关系
                    var wareLocationVsContainer = await _wareLocationVsContainerRep.DetachedEntities.FirstOrDefaultAsync(
                        n => n.ContainerCode == wareContainer.Code && n.LocationVsContainerStatus == CommonStatus.ENABLE);
                    if (wareLocationVsContainer == null) throw Oops.Oh("托盘库位关系不存在！");
                    //检查库位
                    var wareLocation = await _wareLocationRep.DetachedEntities.FirstOrDefaultAsync(p => p.Code == wareLocationVsContainer.LocationCode && p.LocationStatus == LocationStatusEnum.cunhuo);
                    if (wareLocation == null) throw Oops.Oh("库位不存在！");

                    //1.1创建出库记录
                    var cvmModelList = await _wareContainerVsMaterialRep.DetachedEntities.Where(z =>
                      z.ContainerCode == containerCode && z.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();
                    foreach (var item in cvmModelList)
                    {
                        item.ContainerVsMaterialStatus = CommonStatus.DELETED;
                        await _wareContainerVsMaterialRep.UpdateAsync(item);
                    }

                    //1.2创建出库任务
                    var OrderNo = "N/A";
                    if (cvmModelList.Count > 0) OrderNo = cvmModelList.FirstOrDefault().OrderNo;
                    var taskModel = new WareTask()
                    {
                        OrderNo = OrderNo,
                        TaskModel = TaskModel.SHOUDONG,
                        TaskType = TaskType.Out,
                        TaskNo = YitIdHelper.NextId().ToString(),
                        TaskName = orderModel.OrderType == IssueTypeEnum.DIAOBO ? TaskNameConst.DiaoBoDan_ManualOut : TaskNameConst.ShouDongDan_ManualOut,
                        TaskStatus = TaskStatusEnum.Complete,
                        Priority = 1,
                        ContainerCode = containerCode,
                        FromLocationCode = wareLocation.Code,
                        ToLocationCode = "N/A",
                    };
                    await _wareTaskRep.InsertNowAsync(taskModel);

                    //1.3扣减库存和组盘数量
                    foreach (var item in containerOrderDetailsList)
                    {
                        var updatestockModel = await _wareStockRep.FirstOrDefaultAsync(z => z.Code == item.Code && z.ContainerCode == item.ContainerCode);
                        if (updatestockModel == null) continue;
                        var cvmModel = cvmModelList.FirstOrDefault(z => z.Code == item.Code && z.ContainerCode == item.ContainerCode);
                        if (cvmModel == null) continue;
                        var number = item.OrderQuantity - item.ActualQuantity;
                        if (updatestockModel.StockQuantity > item.OrderQuantity)
                        {
                            item.ActualQuantity += number;
                            updatestockModel.StockQuantity -= number;
                            updatestockModel.CurrentQuantity -= number;
                            await _wareStockRep.UpdateAsync(updatestockModel);
                            cvmModel.BindQuantity -= number;
                        }
                        else
                        {
                            item.ActualQuantity += updatestockModel.CurrentQuantity;
                            await _wareStockRep.DeleteAsync(updatestockModel);
                            cvmModelList.Remove(cvmModel);
                        }
                        //新增分拣
                        var wareSortOrder = new WareSortOrder()
                        {
                            OrderNo = orderModel.OrderNo,
                            OrderDetailID = item.Id,
                            ContainerCode = item.ContainerCode,
                            LocationCode = item.LocationCode,
                            ContainerOrderNo = OrderNo,
                            ProjectCode = item.ProjectCode,
                            Code = item.Code,
                            Name = item.Name,
                            SpecificationModel = item.SpecificationModel,
                            Unit = item.Unit ?? "",
                            InspectionMethod = item.InspectionMethod,
                            SortQuantity = number,
                            ActualQuantity = number,
                            SortStatus = SortStatusEnum.Completed
                        };
                        await _wareSortOrderRep.InsertAsync(wareSortOrder);
                    }

                    OrderNo = YitIdHelper.NextId().ToString();
                    //2.1新增入库组盘记录
                    foreach (var item in cvmModelList)
                    {
                        //新增一条组盘信息
                        var model = item.Adapt<WareContainerVsMaterial>();
                        model.Id = YitIdHelper.NextId();
                        model.OrderNo = OrderNo;
                        model.ContainerCode = wareContainer.Code;
                        model.ContainerId = wareContainer.Id;
                        model.ContainerVsMaterialStatus = CommonStatus.ENABLE;
                        await _wareContainerVsMaterialRep.InsertAsync(model);
                    }
                    //2.2.新增任务
                    var taskRkModel = new WareTask()
                    {
                        OrderNo = OrderNo,
                        TaskModel = TaskModel.SHOUDONG,
                        TaskType = TaskType.In,
                        TaskNo = YitIdHelper.NextId().ToString(),
                        TaskName = orderModel.OrderType == IssueTypeEnum.DIAOBO ? TaskNameConst.DiaoBoDan_ManualOut : TaskNameConst.ShouDongDan_ManualOut,
                        TaskStatus = TaskStatusEnum.Complete,
                        Priority = 1,
                        ContainerCode = containerCode,
                        FromLocationCode = "N/A",
                        ToLocationCode = wareLocation.Code,
                    };
                    await _wareTaskRep.InsertNowAsync(taskRkModel);
                }
            }
        }

        /// <summary>
        /// 扫描单据号
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("GetOrderNo")]
        public async Task<List<WareOrderDetails>> GetMaterialByOrderNo([FromQuery] OrderNoInput input)
        {
            // 查询单据类型对应的ID
            var orderCategory = (await _wareDictDataRep.FirstOrDefaultAsync(z => z.Value == input.OrderCategory)).Code;
            if(orderCategory == null) throw Oops.Oh("不存在此单据类别！");

            var wareOrderDetails = await _wareOrderDetailsRep.DetachedEntities.Where(n => n.WareOrder.OrderNo.Equals(input.OrderNo) 
            && n.WareOrder.OrderCategory.Equals(orderCategory)).ToListAsync();
            if (wareOrderDetails.Count == 0) throw Oops.Oh("单据不存在！");
            return wareOrderDetails;
        }

        ///<summary>
        /// 查询单据类别
        /// </summary>
        /// <returns></returns>
        [HttpGet("CategoryList")]
        public async Task<List<string>> CategoryList()
        {
            var CategoryMode = new List<string>();
            CategoryMode.Add("库位调拨单");
            CategoryMode.Add("装配调拨单");
            CategoryMode.Add("异库调拨单");

            return CategoryMode;
        }

        /// <summary>
        /// 获取库存信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("GetWareStock")]
        public async Task<List<StockListOutput>> GetWareStock([FromQuery] CodeInput input)
        {
            return await _wareStockRep.Where(n => n.Code == input.Code && n.ProjectCode == input.ProjectCode
            && n.SpecificationModel == input.SpecificationModel && n.CurrentQuantity > 0)
                .ProjectToType<StockListOutput>().ToListAsync();
        }

        /// <summary>
        /// 扫描容器
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("GetContainerByMaterail")]
        public async Task<MaterialIssueOutput> GetContainerByMaterail([FromQuery] MaterialForContainerIssueInput input)
        {
            //检查托盘
            var wareContainer = await _wareContainerRep.FirstOrDefaultAsync(z => z.Code == input.ContainerCode);
            if (wareContainer == null) throw Oops.Oh("容器信息不存在!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.jinyong) throw Oops.Oh("容器已禁用!");
            if (wareContainer.ContainerStatus != ContainerStatusEnum.kuwei) throw Oops.Oh("容器不在库位中!");

            //检查库位与容器关系
            var wareLocationVsContainer = await _wareLocationVsContainerRep.DetachedEntities.Where(z => z.WareContainer.Code == input.ContainerCode
            && z.LocationVsContainerStatus == CommonStatus.ENABLE).ProjectToType<WareLocationVsContainer>().FirstOrDefaultAsync();
            if (wareLocationVsContainer == null) throw Oops.Oh("库位与容器关系不存在!");

            //判断是否在任务中
            var isExit = await _wareTaskRep.AnyAsync(n => n.TaskStatus != TaskStatusEnum.Complete && n.ContainerCode == wareLocationVsContainer.ContainerCode);
            if (isExit) throw Oops.Oh("容器存在未完成任务!");

            //判断容器与物料
            var wareContainerVsMaterials = await _wareContainerVsMaterialRep.DetachedEntities
            .Where(p => p.WareContainer.Code == wareLocationVsContainer.WareContainer.Code && p.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();

            return new MaterialIssueOutput
            {
                LocationCode = wareLocationVsContainer.WareLocation.Code,
                WareContainer = wareLocationVsContainer.WareContainer.Adapt<WareContainerIssueOutput>(),
                WareContainerVsMaterials = wareContainerVsMaterials.Adapt<List<WareContainerVsMaterialIssueOutput>>(),
            };
        }

        /// <summary>
        /// 扫描库位
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("GetLocationByMaterail")]
        public async Task<MaterialIssueOutput> GetLocationByMaterail(MaterialForLocationIssueInput input)
        {
            //检查托盘
            var wareLocation = await _wareLocationRep.FirstOrDefaultAsync(z => z.Code == input.LocationCode);
            if (wareLocation == null) throw Oops.Oh("库位信息不存在!");
            if (wareLocation.LocationStatus == LocationStatusEnum.jinyong) throw Oops.Oh("库位已禁用!");
            if (wareLocation.LocationStatus != LocationStatusEnum.cunhuo) throw Oops.Oh("无库存不能出库!");

            //检查库位与容器关系
            var wareLocationVsContainer = await _wareLocationVsContainerRep.DetachedEntities.Where(z => z.WareLocation.Code == input.LocationCode
            && z.LocationVsContainerStatus == CommonStatus.ENABLE).ProjectToType<WareLocationVsContainer>().FirstOrDefaultAsync();
            if (wareLocationVsContainer == null) throw Oops.Oh("库位与容器关系不存在!");

            //判断是否在任务中
            var isExit = await _wareTaskRep.AnyAsync(n => n.TaskStatus != TaskStatusEnum.Complete && n.ContainerCode == wareLocationVsContainer.ContainerCode);
            if (isExit) throw Oops.Oh("容器存在未完成任务!");

            //判断容器与物料
            var wareContainerVsMaterials = await _wareContainerVsMaterialRep.DetachedEntities
            .Where(p => p.WareContainer.Code == wareLocationVsContainer.WareContainer.Code && p.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();

            return new MaterialIssueOutput
            {
                LocationCode = wareLocationVsContainer.WareLocation.Code,
                WareContainer = wareLocationVsContainer.WareContainer.Adapt<WareContainerIssueOutput>(),
                WareContainerVsMaterials = wareContainerVsMaterials.Adapt<List<WareContainerVsMaterialIssueOutput>>(),
            };
        }

        /// <summary>
        /// 盘点出库获取数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("PanDianList")]
        public async Task<List<PanDianOutListOutput>> PanDianList([FromQuery] QueryPanDianOutListInput input)
        {
            var list = new List<PanDianOutListOutput>();

            // 根据所属库区查询所有的存货信息
            var wareLocationList = await _wareLocationRep.DetachedEntities.Where(z => z.LocationStatus == LocationStatusEnum.cunhuo)
                .Where(input.AreaID != 0, z => z.AreaID == input.AreaID)
                .Where(input.Aisle != 0, z => z.Aisle == input.Aisle)
                .Where(input.RowNo != 0, z => z.RowNo == input.RowNo)
                .Where(input.ColumnNo != 0, z => z.ColumnNo == input.ColumnNo)
                .Where(input.LayerNo != 0, z => z.LayerNo == input.LayerNo)
                .ToListAsync();

            foreach (var item in wareLocationList)
            {
                var model = new PanDianOutListOutput();

                var wareStock = await _wareStockRep.FirstOrDefaultAsync(z => z.LocationCode == item.Code);
                if (wareStock != null && wareStock.CurrentQuantity > new decimal(0.00))
                {
                    model.Aisle = item.Aisle;
                    model.RowNo = item.RowNo;
                    model.ColumnNo = item.ColumnNo;
                    model.LayerNo = item.LayerNo;
                    model.ContainerCode = wareStock.ContainerCode;
                    model.LocationCode = item.Code;

                    list.Add(model);
                }
            }

            return list;
        }

        /// <summary>
        /// 盘点出库确认
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("PanDianListOut")]
        public async Task PanDianListOut([FromBody] List<PanDianOutListOutput> input)
        {
            try
            {
                foreach (var listItem in input)
                {
                    var stockList = await _wareStockRep.Where(z => z.ContainerCode == listItem.ContainerCode).ToListAsync();
                    if (stockList.Count == 0) throw Oops.Oh("库存不足不能出库！");

                    //检查托盘
                    var wareContainer = await _wareContainerRep.FirstOrDefaultAsync(n => n.Code == listItem.ContainerCode && n.ContainerStatus == ContainerStatusEnum.kuwei);
                    if (wareContainer == null) throw Oops.Oh("托盘不存在！");

                    //检查库位
                    var locationModel = await _wareLocationRep.FirstOrDefaultAsync(p => p.Code == listItem.LocationCode && p.LocationStatus == LocationStatusEnum.cunhuo);
                    if (locationModel == null) throw Oops.Oh("库位不存在！");

                    //检查关系
                    var wareLocationVsContainer = await _wareLocationVsContainerRep.FirstOrDefaultAsync(
                        n => n.ContainerCode == listItem.ContainerCode && n.LocationCode == listItem.LocationCode && n.LocationVsContainerStatus == CommonStatus.ENABLE);
                    if (wareLocationVsContainer == null) throw Oops.Oh("托盘库位关系不存在！");

                    var wareContainerVsMaterialList = await _wareContainerVsMaterialRep.DetachedEntities.Where(p => p.ContainerCode == listItem.ContainerCode
                    && p.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();

                    //2023/3/7 根据库位ID进行任务类型 可以写死，无法就是三种情况，立体库，avg平库，其他类型库位
                    //一楼立体库
                    if (locationModel.AreaID == 374444843716677)
                    {

                    }
                    else if (locationModel.AreaID == 374444736143429) //一楼平库
                    {

                    }
                }
            }
            catch (Exception ex)
            {
                throw Oops.Oh("[PanDianListOut]盘点出库确认下发异常：" + ex.StackTrace + "," + ex.Message);
            }
            finally
            {
            }
        }

        /// <summary>
        /// 呼叫AGV
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task CallAgvOut([FromBody] CallAgvInput input)
        {
            try
            {
                //查询起始站点信息
                var StartStite = _wareLocationRep.DetachedEntities.Where(z => z.Code == input.StartCode).FirstOrDefault();
                if (StartStite.LocationStatus != LocationStatusEnum.cunhuo) throw Oops.Oh("起始站点无存货信息！");

                //查询目标站点信息
                var EndStite = _wareLocationRep.DetachedEntities.Where(z => z.Code == input.EndCode).FirstOrDefault();
                if (EndStite.LocationStatus != LocationStatusEnum.kongxian) throw Oops.Oh("目标站点不为空闲状态！");

                //查询托盘库区关系
                var wareConvsLon = await _wareLocationVsContainerRep.FirstOrDefaultAsync(z => z.LocationVsContainerStatus == CommonStatus.ENABLE && z.LocationCode == StartStite.Code);

                //查询托盘信息
                var wareContain = await _wareContainerRep.FirstOrDefaultAsync(z => z.Code == wareConvsLon.ContainerCode);

                #region 创建AGV任务
                // 创建AGV任务
                var taskNo = YitIdHelper.NextId().ToString(); //系统生成任务号

                // 调用AGV服务创建指定名称的订单
                var createTransportOrders = new CreateTransportOrdersInput();
                createTransportOrders.TaskNo = taskNo;
                createTransportOrders.intendedVehicle = "Vehicle-01"; //立体库执行车辆
                var destList = new List<DestinationsInput>();
                var dest1 = new DestinationsInput()
                {
                    locationName = StartStite.Code, //起始地面站点
                    operation = "Load cargo:00" //地面层数是0，Load是取货
                };
                var dest2 = new DestinationsInput()
                {
                    locationName = EndStite.Code, //目标地面站点
                    operation = "Unload cargo:00"  //地面层数是0，Unload是放货
                };
                destList.Add(dest1);
                destList.Add(dest2);

                createTransportOrders.destinations = destList;
                var createTransportOrdersOutput = await _agvService.CreateTransportOrders(createTransportOrders);
                // 写日志文件
                Log.Error($"[MaterialOut-LES出库任务回调][createTransportOrdersOutput:{createTransportOrdersOutput.ToJson()}]");

                if (createTransportOrdersOutput.result == "success")
                {
                    // 创建AGV任务
                    var wareAgvTask = new WareAgvTask()
                    {
                        TaskType = "呼叫AGV",
                        StartPlace = StartStite.Code, //起始站点位置
                        EndPlace = EndStite.Code, //目标站点位置
                        TransportOrder = taskNo,
                        AgvState = "PRISTINE",
                        ContainerCode = wareContain.Code,
                        CreatedUserName = CurrentUserInfo.Name
                    };
                    await _wareAgvTaskRep.InsertAsync(wareAgvTask);

                    //更新站点状态(起始位置更新为待出，目标位置更新为待入)
                    StartStite.LocationStatus = LocationStatusEnum.daichu;
                    await _wareLocationRep.UpdateAsync(StartStite);
                    EndStite.LocationStatus = LocationStatusEnum.dairu;
                    await _wareLocationRep.UpdateAsync(EndStite);

                    //构建容器与agv库位关系表
                    var wareLocationVsContainerModel = new WareLocationVsContainer()
                    {
                        LocationId = EndStite.Id,
                        LocationCode = EndStite.Code,
                        ContainerId = wareContain.Id,
                        ContainerCode = wareContain.Code,
                        LocationVsContainerStatus = CommonStatus.ENABLE
                    };
                    await _wareLocationVsContainerRep.InsertAsync(wareLocationVsContainerModel);
                }
                #endregion

            }
            catch (Exception ex)
            {
                throw Oops.Oh("[CallAgvOut]呼叫AGV下发异常：" + ex.StackTrace + "," + ex.Message);
            }
            finally
            {
            }
        }
    }
}


